/*
 * DefaultIndexer.java
 *
 * Created on February 19, 2008, 9:11 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.afaker.searth.core.index;

import com.afaker.searth.core.index.Indexer;
import com.afaker.searth.core.index.handler.DocumentHandler;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.LockObtainFailedException;

/**
 *
 * @author bruce
 */
public abstract class DefaultIndexer implements Indexer {

    private Properties properties;
    private Logger log = Logger.getLogger(DefaultIndexer.class);
    public static String indexDir;
    private IndexWriter writer;
    protected DocumentHandler docHandler;
    protected List<Document> documents = new ArrayList<Document>();

    public void setDocumentHandler(DocumentHandler docHandler) {
        this.docHandler = docHandler;
    }

    public DocumentHandler getDocumentHandler() {
        return docHandler;
    }

    public String getIndexDir() {
        return indexDir;
    }

    /**
     * Creates a new instance of DefaultIndexer
     */
    public DefaultIndexer() {
        properties = new Properties();
    }
    /**
     * Do actual index work.But it still delegate sub classes to do the detailes.
     * @throws java.io.IOException
     */
    public final void index() throws IOException {
        //Load index setting property file and read index directory value.
        properties.load(
                DefaultIndexer.class.getClassLoader().getResourceAsStream(
                "index.properties"));
        indexDir = properties.getProperty("index.dir");
        log.info("Index directory: " + indexDir);
        
        Date start = new Date();
        //Sub classes do the boring stuffs.
        indexDocuments();
        
        File file = new File(indexDir);
        boolean isCreated = false;
        if (file.listFiles().length < 1) {
            isCreated = true;
        }
        try {
            writer = new IndexWriter(indexDir, new StandardAnalyzer(), isCreated);
        } catch (LockObtainFailedException ex) {
            log.error(ex.getMessage(), ex);
        } catch (IOException ex) {
            log.error(ex.getMessage(), ex);
        }
        for (int i = 0; i < documents.size(); i++) {
            Document doc = documents.get(i);
            if (doc != null) {
                writer.addDocument(doc);
            }
        }
        try {
            log.info("Optimizing...");
            writer.optimize();
        } catch (CorruptIndexException ex) {
            log.error(ex.getMessage() + " at index(File)", ex);
        } catch (IOException ex) {
            log.error(ex.getMessage() + " at index(File)", ex);
        }
        close();
        Date end = new Date();
        log.info(end.getTime() - start.getTime() + " total milliseconds");
    }

    private void close() {
        try {
            log.info("Closing...");
            writer.close();
        } catch (CorruptIndexException ex) {
            log.error(ex.getClass(), ex);

        } catch (IOException ex) {
            log.error(ex.getClass(), ex);
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
    // TODO code application logic here
    }
    
    /**
     * Sub Classes implement the method and index what you want to.
     */
    protected abstract void indexDocuments();
}
